﻿using UnityEngine;
using UnityEngine.Pool;
using System.Collections;
using System.Collections.Generic;
using QFramework;
using UnityEngine.SceneManagement;

namespace GameLogic
{
    public class GoPool : SingletonBehaviour<GoPool>
    {
        private readonly Dictionary<string, IObjectPool<GameObject>> _pathPools
            = new Dictionary<string, IObjectPool<GameObject>>();

        /*private Dictionary<GameObject, IObjectPool<GameObject>> instanceToPool
            = new Dictionary<GameObject, IObjectPool<GameObject>>();*/
        
        private readonly Dictionary<GameObject, string> _inst2Path
            = new Dictionary<GameObject, string>();
        
        private bool _isUseChildPoolNode = true;
        private bool _isUseStrategy = true;

        /*private class PoolCoroutineRunner : MonoBehaviour
        {
        }

        private static PoolCoroutineRunner runner;

        private static void InitRunner()
        {
            if (runner == null)
            {
                GameObject runnerObj = new GameObject("ObjectPoolProRunner");
                Object.DontDestroyOnLoad(runnerObj);
                runner = runnerObj.AddComponent<PoolCoroutineRunner>();
                // 订阅场景卸载事件，自动清理对象池
                SceneManager.sceneUnloaded += _ => { ClearAll(); };
            }
        }*/
        
        internal Dictionary<string, IObjectPool<GameObject>> PathPools => _pathPools;
        internal Dictionary<GameObject, string> Inst2Path => _inst2Path;

        protected override void OnLoad()
        {
            gameObject.AddComponent<ActivePoolStrategy>();
        }

        public void Register(string path, int preloadCount = 0, int maxPoolSize = 256)
        {
            if (_pathPools.ContainsKey(path))
            {
                Debug.LogWarning($"Path {path} 已经注册过对象池！");
                return;
            }

            //var maxPoolSize = GetComponent<ActivePoolStrategy>().CapacityOnePool;
            IObjectPool<GameObject> pool = new ObjectPool<GameObject>(
                createFunc: () =>
                {
                    //GameObject obj = Object.Instantiate(prefab);
                    GameObject obj = GameModule.Resource.LoadGameObject(path);
                    obj.SetActive(false); // 初始创建时先隐藏
                    return obj;
                },
                actionOnGet: obj => { obj.SetActive(true); }, // 取出时激活
                actionOnRelease: obj =>
                {
                    obj.SetActive(false);
                    if(_isUseChildPoolNode)
                        Parent2ChildPoolNode(path, obj);
                }, // 回收时隐藏
                actionOnDestroy: obj =>
                {
                    _inst2Path.Remove(obj);
                    Object.Destroy(obj);
                }, // 销毁时彻底销毁
                collectionCheck: true,
                defaultCapacity: preloadCount,
                maxSize: maxPoolSize
            );

            _pathPools[path] = pool;

            if(_isUseChildPoolNode)
                CreateChildPoolNode(path);

            // 预热逻辑
            if (preloadCount > 0)
            {
                Preload(pool, preloadCount);
                
                if(_isUseStrategy)
                    GetComponent<ActivePoolStrategy>().OnTouch(path);
            }
        }

        private void CreateChildPoolNode(string path)
        {
            var childPoolNode = transform.Find($"{path}");
            if (childPoolNode != null) return;
            var childPoolNodeGo = new GameObject($"{path}");
            childPoolNodeGo.transform.parent = transform;
        }

        private void Parent2ChildPoolNode(string path,GameObject go)
        {
            var childPoolNode = transform.Find($"{path}");
            go.transform.SetParent(childPoolNode);
        }

        private void Preload(IObjectPool<GameObject> pool, int preloadCount)
        {
            List<GameObject> tempList = new List<GameObject>();
            for (int i = 0; i < preloadCount; i++)
            {
                GameObject obj = pool.Get(); // 从池中获取以创建对象
                tempList.Add(obj);
            }

            foreach (GameObject obj in tempList)
            {
                pool.Release(obj); // 立即释放回池
            }

            tempList.Clear();
        }

        public GameObject Spawn(string path,float autoRecycleAfterTime=0)
        {
            if (!_pathPools.ContainsKey(path))
            {
                Debug.LogWarning($"Path {path} 未注册对象池，将自动注册！");
                Register(path, 0); // 未注册则自动注册，不预热
            }

            IObjectPool<GameObject> pool = _pathPools[path];
            GameObject obj = pool.Get();
            if (autoRecycleAfterTime > 0)
            {
                var autoRecycle = obj.GetOrAddComponent<AutoRecycle>();
                autoRecycle.recycleAfterTime = 2;
                autoRecycle.StartTimer();
            }
            if(_isUseStrategy)
                GetComponent<ActivePoolStrategy>().OnTouch(path);
            //instanceToPool[obj] = pool; // 记录对象归属
            _inst2Path[obj] = path;
            return obj;
        }

        public void Recycle(GameObject obj)
        {
            if (obj == null) return;

            //if (!instanceToPool.ContainsKey(obj))
            if (!_inst2Path.TryGetValue(obj, out var path))
            {
                Debug.LogError($"对象 {obj.name} 不属于任何对象池，无法回收！请检查是否已回收或未通过ObjectPoolPro获取。");
                return;
            }

            if(_isUseStrategy)
                GetComponent<ActivePoolStrategy>().OnTouch(path);
            
            //IObjectPool<GameObject> pool = instanceToPool[obj];
            IObjectPool<GameObject> pool = _pathPools[path];
            //instanceToPool.Remove(obj); // 从活跃映射中移除
            _inst2Path.Remove(obj); // 从活跃映射中移除
            pool.Release(obj); // 释放对象回池
            
            if(_isUseStrategy)
                GetComponent<ActivePoolStrategy>().OnRecycleEnd(pool, path);
        }

        public void Recycle(GameObject obj, float delay)
        {
            if (obj == null) return;

            if (delay <= 0f)
            {
                Recycle(obj); // 立即回收
            }
            else
            {
                //InitRunner(); // 确保协程执行器已初始化
                //runner.StartCoroutine(DoRecycleAfter(obj, delay));
                StartCoroutine(DoRecycleAfter(obj, delay));
            }
        }

        private IEnumerator DoRecycleAfter(GameObject obj, float delay)
        {
            yield return new WaitForSeconds(delay);
            // 在延迟结束后再次检查对象是否有效，防止在等待期间被外部销毁
            if (obj != null)
            {
                Recycle(obj);
            }
        }

        public void RemovePool(string path)
        {
            _pathPools.Remove(path);

            if (!_isUseChildPoolNode) return;
            
            var childPoolNode = transform.Find($"{path}");
            if (childPoolNode == null) return;
            
            Destroy(childPoolNode.gameObject);
        }

        public void ClearAll()
        {
            foreach (var pool in _pathPools.Values)
            {
                pool.Clear(); // 清空每个池，销毁其所有对象
            }

            _pathPools.Clear(); // 清空所有 Prefab 池的引用
            //instanceToPool.Clear(); // 清空所有实例的映射
            _inst2Path.Clear(); // 清空所有实例的映射

            // 可选：如果runner是DontDestroyOnLoad，可以在这里销毁runnerObj
            // if (runner != null)
            // {
            //     Object.Destroy(runner.gameObject);
            //     runner = null;
            // }
        }
    }
}